home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJSRC111.ZIP / go32 / paging.c < prev    next >
C/C++ Source or Header  |  1993-12-05  |  35KB  |  1,245 lines

  1. /* This is file PAGING.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* Modified for DPMI Implement by H.Tsubakimoto */
  17. /* NUR paging algorithm by rcharif@math.utexas.edu */
  18. /* Merged DPMI with V1.09+ code C. Sandmann sandmann@clio.rice.edu */
  19.  
  20. #include <stdio.h>
  21. #include <dos.h>
  22. #include <fcntl.h>
  23. #include <io.h>
  24. #include <sys/stat.h>
  25. #include <bios.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28.  
  29. #include "gotypes.h"
  30. #include "paging.h"
  31. #include "graphics.h"
  32. #include "tss.h"
  33. #include "idt.h"
  34. #include "gdt.h"
  35. #include "valloc.h"
  36. #include "dalloc.h"
  37. #include "utils.h"
  38. #include "aout.h"
  39. #include "mono.h"
  40. #include "vcpi.h"
  41. #include "dpmi.h"
  42. #include "extdebug.h"
  43. #include "exphdlr.h"
  44. #include "stubinfo.h"
  45. #include "proginfo.h"
  46. #include "control.h"
  47.  
  48. #define VERBOSE 0
  49.  
  50. /* #define KEEP_ON_EXEC */
  51.  
  52. #define MAX_PAGING_NUM 2
  53.  
  54.  
  55. #define DOS_PAGE 256            /*  1MB / 4KB = 256 Pages  */
  56.  
  57.  
  58. extern char transfer_buffer[4096];
  59.  
  60. extern word32 ptr2linear(void far *ptr);
  61.  
  62. struct {
  63.   word16 limit;
  64.   word32 base;
  65. } gdt_phys, idt_phys;
  66.  
  67. CLIENT  client;         /*  VCPI Change Mode Structure  */
  68. word32  abs_client;     /*  _DS * 16L + &client         */
  69. far32   vcpi_entry;
  70. SYS_TBL int_descriptor;
  71. SYS_TBL gbl_descriptor;
  72.  
  73. extern word16 vcpi_installed;   /*  VCPI Installed Flag  */
  74. extern near protect_entry();
  75. word32 DPMI_STACK = 0x40000L; /* 256Kb Min */
  76. #define DPMIgetpage 0xffffL /* 64K instead of 4K for speed */
  77. DPMImemory DPMImem;         /* protected memory block */
  78. static word32 oldbase;     /* DPMI selector base for allocated memory */
  79. static word16 DPMIselect; /* selectors for application */
  80.                           /* DPMIselect + 0  : data selector */
  81.                           /* DPMIselect + 8  : code selector */
  82.                           /* DPMIselect + 16 : stack selector */ 
  83.                           /* DPMIselect + 24 : linear 1Mb range */ 
  84.  
  85. extern TSS *utils_tss;
  86. extern int debug_mode;
  87. extern word32 mem_avail;
  88. extern int self_contained;
  89. extern long header_offset;
  90.  
  91. word16 core_selector, arena_ds, arena_cs;
  92.  
  93. AREAS areas[MAX_AREA];
  94. #if VERBOSE
  95. static char *aname[MAX_AREA] = {
  96.         "text ",
  97.         "data ",
  98.         "bss  ",
  99.         "arena",
  100.         "stack",
  101.         "vga  ",
  102.         "syms ",
  103.         "syms2",
  104.         "emu"
  105. };
  106. #endif
  107. static char achar[MAX_AREA] = "tdbmsg?e";
  108.  
  109. word32 far *pd = 0;
  110. word8 pd_seg[1024];
  111. word32 far *vcpi_pt = 0;
  112. word8 paging_buffer[4096*MAX_PAGING_NUM];
  113.  
  114. word32 screen_primary, screen_secondary;
  115.  
  116. word32 ptr2linear(void far *ptr)
  117. {
  118.   return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr);
  119. }
  120.  
  121. static word32 far2pte(void far *ptr, word32 flags)
  122. {
  123.   return (vcpi_pt[(int)(((word32)ptr) >> 24)] & 0xfffff000L) | flags;
  124. }
  125.  
  126. static word32 pn2pte(unsigned pn, word32 flags)
  127. {
  128.   return (vcpi_pt[pn] & 0xfffff000L) | flags;
  129. }
  130.  
  131. static void setDPMISelectors(int firsttime)
  132. {
  133.   int selfail;
  134.  
  135.   selfail = 0;
  136.   if(!DPMIassignSelector(DPMIselect, 0xc0b3, DPMImem.address,
  137.       DPMImem.bytes - 1 ) ) selfail = 1; /* win 3.1 needs f, 3.0 b */
  138.  
  139.   if(firsttime){
  140.     if(!DPMIassignSelector(DPMIselect + 8, 0xc0bb, DPMImem.address, 
  141.         DPMImem.bytes - 1) ) selfail |= 2;
  142.     if(!DPMIassignSelector(DPMIselect + 16, 0xc0b7, DPMImem.address,
  143.         (areas[A_stack].first_addr - 1) ) ) selfail |= 4;
  144.   } else if(DPMImem.address != oldbase) {
  145.     if(!DPMISelectorBase(DPMIselect + 8, DPMImem.address) ) selfail |= 10;
  146.     if(!DPMISelectorBase(DPMIselect + 16, DPMImem.address) ) selfail |= 12;
  147.     if(using_external_debugger) {
  148.       DPMIrealMode();
  149.       clear_break_DPMI();       /* This clears the breakpoints */
  150.       set_break_DPMI();         /* This resets them with new base */
  151.       DPMIprotectedMode();
  152.     }
  153.   }
  154.   oldbase = DPMImem.address;
  155.  
  156. #if VERBOSE
  157.   if(selfail) {
  158.     /* For some reason stack #4 fails under OS2 but it still works; thus
  159.        the workaround is to ignore this section unless in verbose mode */
  160.     DPMIrealMode();
  161.     fprintf(stderr,"DPMI: AssignSelector %d failed!\n",selfail);
  162. /*    exit(3);  */
  163.     DPMIprotectedMode();  /* Only if exit commented */
  164.   }
  165. #endif
  166. }
  167.  
  168. void loadAout(const AREAS* areas)
  169. {
  170.   word32 count = areas->last_addr + 1 - areas->first_addr;
  171.  
  172.   if (count > 0) {
  173.     word32 loadAddr = areas->first_addr;
  174.     lseek(areas->fileno, areas->foffset, 0);
  175.     while (count > 0) {
  176.       word16 readBytes;
  177.       word16 bytes = (count > 4096) ? 4096 : (word16)count;
  178.       readBytes = read(areas->fileno, transfer_buffer, bytes);
  179.       if (readBytes < bytes) memset(transfer_buffer + readBytes, 0, bytes - readBytes);
  180.       memput(loadAddr, transfer_buffer, bytes);
  181.       loadAddr += bytes;
  182.       count -= bytes;
  183.     }
  184.   }
  185. }
  186.  
  187. void clearDPMIstate(void)
  188. {
  189.   DPMIfree(&DPMImem);  /* QDPMI bug fix - child processes don't free memory */
  190. }
  191.  
  192. static void saveDPMIstate(void)
  193. {
  194.   int a;
  195.   word32 firsta, lengtha;
  196.   word16 bytes;
  197.   unsigned block;
  198.  
  199.   block = 0;
  200.   for (a=0; a<MAX_AREA; a++) {
  201.     firsta = areas[a].first_addr;
  202.     if ( a == A_stack ) firsta = a_tss.tss_esp & 0xfffff000L;
  203.     lengtha = areas[a].last_addr - firsta + 1;
  204.     while (lengtha > 0) {
  205.       bytes = (lengtha > 4096) ? 4096 : (word16)lengtha;
  206.       Pmemget(DPMIselect, firsta, paging_buffer, bytes);
  207.       dwrite(paging_buffer, block++);
  208.       firsta += bytes;
  209.       lengtha -= bytes;
  210.     }
  211.   }
  212.   DPMIprotectedMode();
  213.   DPMIfree(&DPMImem);
  214.   restoreDPMIvector();
  215.   DPMIrealMode();
  216. }
  217.  
  218. static void restoreDPMIstate(void)
  219. {
  220.   int a;
  221.   word32 firsta, lengtha;
  222.   word16 bytes;
  223.   unsigned block;
  224.  
  225.   DPMIprotectedMode();
  226.   setDPMIvector();
  227.   lengtha = (areas[A_arena].last_addr + 1 + DPMIgetpage) & ~DPMIgetpage;
  228.   if (! DPMIalloc(&DPMImem, lengtha)) {
  229.     DPMIrealMode();
  230.     fprintf(stderr,"\nDPMI: Not enough memory (0x%08lx bytes).\n", lengtha);
  231.     exit(3);
  232.   }
  233.   setDPMISelectors(0);
  234.   DPMIrealMode();
  235.   firsta = areas[A_arena].last_addr + 1;
  236.   if(lengtha > firsta)
  237.     Pmemset(DPMIselect, firsta, 0, lengtha - firsta );
  238.  
  239.   block = 0;
  240.   for (a=0; a<MAX_AREA; a++) {
  241.     firsta = areas[a].first_addr;
  242.     if ( a == A_stack ) firsta = a_tss.tss_esp & 0xfffff000L;
  243.     lengtha = areas[a].last_addr - firsta + 1;
  244.     while (lengtha > 0) {
  245.       bytes = (lengtha > 4096) ? 4096 : (word16)lengtha;
  246.       dread(paging_buffer, block++);
  247.       Pmemput(DPMIselect, firsta, paging_buffer, bytes);
  248.       firsta += bytes;
  249.       lengtha -= bytes;
  250.     }
  251.   }
  252. }
  253.  
  254. int changeBreak(word32 breakPoint)
  255. {
  256.   word32 oldbytes, newbytes;
  257.  
  258.   newbytes = (breakPoint + DPMIgetpage) & ~DPMIgetpage; /* 64K for performance */
  259.   oldbytes = DPMImem.bytes;
  260.   if (newbytes < areas[A_arena].first_addr) newbytes=areas[A_arena].first_addr;
  261. #if VERBOSE
  262.   fprintf(stderr,"changeBreak: old=0x%08lx  break=0x%08lx  new=0x%08lx\n",
  263.     oldbytes, breakPoint, newbytes);
  264. #endif
  265.   if (DPMImem.bytes != newbytes) {
  266.     DPMIprotectedMode();
  267.     if (! DPMIrealloc(&DPMImem, newbytes)) {
  268.       DPMIrealMode();
  269.       fprintf(stderr,"\nDPMI: Not enough memory (0x%08lx bytes).\n", newbytes);
  270.       return 0;
  271.     }
  272.     setDPMISelectors(0);
  273.     DPMIrealMode();
  274.   }
  275.   if(newbytes > oldbytes) 
  276.     Pmemset(DPMIselect, oldbytes, 0, newbytes - oldbytes );
  277.   return 1;
  278. }
  279.  
  280. /*  VCPI Get Interface  */
  281. void    link_vcpi(word32 far *dir, word32 far *table)
  282. {
  283.  
  284.   vcpi_entry.selector = g_vcpicode * 8;
  285.   vcpi_entry.offset32 = get_interface(table,&gdt[g_vcpicode]);
  286.   client.page_table   = far2pte(dir, 0); /* (word32)dir>>12; */
  287.   client.gdt_address  = ptr2linear(&gdt_phys);
  288.   client.idt_address  = ptr2linear(&idt_phys);
  289.   client.ldt_selector = 0;
  290.   client.tss_selector = g_ctss * 8;
  291.   client.entry_eip    = (word16)protect_entry;
  292.   client.entry_cs     = g_rcode * 8;
  293.  
  294.   abs_client = ptr2linear(&client);
  295. }
  296.  
  297. void handle_screen_swap(word32 far *pt)
  298. {
  299.   struct REGPACK r;
  300.   int have_mono=0;
  301.   int have_color=0;
  302.   int have_graphics=0;
  303.   int save, new;
  304.  
  305.   r.r_ax = 0x1200;
  306.   r.r_bx = 0xff10;
  307.   r.r_cx = 0xffff;
  308.   intr(0x10, &r);
  309.   if (r.r_cx == 0xffff)
  310.     pokeb(0x40, 0x84, 24); /* the only size for CGA/MDA */
  311.  
  312.   if (!vcpi_installed || (pt[0xb8] & (PT_U|PT_W)) == (PT_W|PT_U))
  313.   {
  314.     save = peekb(screen_seg, 0);
  315.     pokeb(screen_seg, 0, ~save);
  316.     new = peekb(screen_seg, 0);
  317.     pokeb(screen_seg, 0, save);
  318.     if (new == ~save)
  319.       have_color = 1;
  320.   }
  321.  
  322.   if (!vcpi_installed || (pt[0xb0] & (PT_U|PT_W)) == (PT_W|PT_U))
  323.   {
  324.     save = peekb(0xb000, 0);
  325.     pokeb(0xb000, 0, ~save);
  326.     new = peekb(0xb000, 0);
  327.     pokeb(0xb000, 0, save);
  328.     if (new == ~save)
  329.       have_mono = 1;
  330.   }
  331.  
  332.   r.r_ax = 0x0f00;
  333.   intr(0x10, &r);
  334.   if ((r.r_ax & 0xff) > 0x07)
  335.     have_graphics = 1;
  336.  
  337.   if (have_graphics && have_mono)
  338.     have_color = 1;
  339.   else if (have_graphics && have_color)
  340.     have_mono = 1;
  341.  
  342.   screen_primary = 0xe00b8000L;
  343.   screen_secondary = 0xe00b0000L;
  344.  
  345.   if (have_color && !have_mono)
  346.   {
  347.     screen_secondary = 0xe00b8000L;
  348.     return;
  349.   }
  350.   if (have_mono & !have_color)
  351.   {
  352.     screen_primary = 0xe00b0000L;
  353.     return;
  354.   }
  355.  
  356.   if ((biosequip() & 0x0030) == 0x0030) /* mono mode, swap! */
  357.   {
  358.     screen_primary = 0xe00b0000L;
  359.     screen_secondary = 0xe00b8000L;
  360.     return;
  361.   }
  362. }
  363.  
  364. void paging_set_file(char *fname)
  365. {
  366.   word32 newbytes;
  367.   word32 far *pt;
  368.   FILEHDR filehdr;
  369.   AOUTHDR aouthdr;
  370.   SCNHDR scnhdr[3];
  371.   GNU_AOUT gnu_aout;
  372.   unsigned short *exe_hdr;
  373.   int i;
  374.   int aout_f;
  375.  
  376.   aout_f = open(fname, O_RDONLY|O_BINARY);
  377.   if (aout_f < 0)
  378.   {
  379.     fprintf(stderr, "Can't open file <%s>\n", fname);
  380.     exit(1);
  381.   }
  382.   
  383.   areas[A_text].fileno = aout_f;
  384.   areas[A_data].fileno = aout_f;
  385.   for (i=A_bss; i<A_max; i++)
  386.     areas[i].fileno = 0;
  387.  
  388.   if (topline_info)
  389.     for (i=0; fname[i]; i++)
  390.       poke(screen_seg, i*2+10, fname[i] | 0x0700);
  391.  
  392.   lseek(aout_f, header_offset, 0);
  393.   read(aout_f, &filehdr, sizeof(filehdr));
  394.  
  395.   if (filehdr.f_magic == 0x5a4d) /* .EXE */
  396.   {
  397.     exe_hdr = (unsigned short *)&filehdr;
  398.     header_offset += (long)exe_hdr[2]*512L;
  399.     if (exe_hdr[1])
  400.       header_offset += (long)exe_hdr[1] - 512L;
  401.     lseek(aout_f, header_offset, 0);
  402.     read(aout_f, &filehdr, sizeof(filehdr));
  403.   }
  404.  
  405.   if (filehdr.f_magic != 0x14c)
  406.   {
  407.     lseek(aout_f, header_offset, 0);
  408.     read(aout_f, &gnu_aout, sizeof(gnu_aout));
  409.     a_tss.tss_eip = gnu_aout.entry;
  410.     aouthdr.tsize = gnu_aout.tsize;
  411.     aouthdr.dsize = gnu_aout.dsize;
  412.     aouthdr.bsize = gnu_aout.bsize;
  413.   }
  414.   else
  415.   {
  416.     read(aout_f, &aouthdr, sizeof(aouthdr));
  417.     a_tss.tss_eip = aouthdr.entry;
  418.     read(aout_f, scnhdr, sizeof(scnhdr));
  419.   }
  420.   arena_cs =
  421.   a_tss.tss_cs = g_acode*8;
  422.   arena_ds =
  423.   a_tss.tss_ds =
  424.   a_tss.tss_es =
  425.   a_tss.tss_fs =
  426.   a_tss.tss_ss = g_adata*8;
  427.   a_tss.tss_esp = 0x7ffffffcL;
  428.  
  429.   if (filehdr.f_magic == 0x14c)
  430.   {
  431.     areas[A_text].first_addr = aouthdr.text_start + ARENA;
  432.     areas[A_text].foffset = scnhdr[0].s_scnptr + header_offset;
  433.     areas[A_text].last_addr = areas[A_text].first_addr + aouthdr.tsize - 1;
  434.   }
  435.   else if (filehdr.f_magic == 0x10b)
  436.   {
  437.     areas[A_text].first_addr = ARENA;
  438.     if (a_tss.tss_eip >= 0x1000)        /* leave space for null reference */
  439.       areas[A_text].first_addr += 0x1000;    /* to cause seg fault */
  440.     areas[A_text].foffset = header_offset;
  441.     areas[A_text].last_addr = areas[A_text].first_addr + aouthdr.tsize + 0x20 - 1;
  442.   }
  443.   else if (debug_mode && filehdr.f_magic == 0x107)
  444.   {
  445.     struct stat sbuf;
  446.     fstat(aout_f, &sbuf);
  447.     areas[A_text].first_addr = ARENA;
  448.     areas[A_text].foffset = 0x20 + header_offset;
  449.     areas[A_text].last_addr = sbuf.st_size + ARENA - 0x20;
  450.   }
  451.   else if (debug_mode)
  452.   {
  453.     struct stat sbuf;
  454.     fstat(aout_f, &sbuf);
  455.     areas[A_text].first_addr = ARENA;
  456.     areas[A_text].foffset = header_offset;
  457.     areas[A_text].last_addr = sbuf.st_size + ARENA;
  458.   }
  459.   else
  460.   {
  461.     fprintf(stderr, "Unknown file type 0x%x (0%o)\n", filehdr.f_magic, filehdr.f_magic);
  462.     exit(-1);
  463.   }
  464.   if (debug_mode)
  465.     fprintf(stderr, "%ld+", aouthdr.tsize);
  466.  
  467.   if (filehdr.f_magic == 0x14c)
  468.   {
  469.     areas[A_data].first_addr = aouthdr.data_start + ARENA;
  470.     areas[A_data].foffset = scnhdr[1].s_scnptr + header_offset;
  471.   }
  472.   else
  473.   {
  474.     areas[A_data].first_addr = (areas[A_text].last_addr+0x3fffffL)&~0x3fffffL;
  475.     areas[A_data].foffset = ((aouthdr.tsize + 0x20 + 0xfffL) & ~0xfffL) + header_offset;
  476.   }
  477.   areas[A_data].last_addr = areas[A_data].first_addr + aouthdr.dsize - 1;
  478.   if (debug_mode)
  479.     fprintf(stderr, "%ld+", aouthdr.dsize);
  480.  
  481.   areas[A_bss].first_addr = areas[A_data].last_addr + 1;
  482.   areas[A_bss].foffset = -1;
  483.   areas[A_bss].last_addr = areas[A_bss].first_addr + aouthdr.bsize - 1;
  484.   if (debug_mode)
  485.     fprintf(stderr, "%ld = %ld\n", aouthdr.bsize,
  486.       aouthdr.tsize+aouthdr.dsize+aouthdr.bsize);
  487.  
  488.   areas[A_arena].first_addr = (areas[A_bss].last_addr + 1 + 7) & ~7L;
  489.   areas[A_arena].last_addr = areas[A_arena].first_addr - 1;
  490.   areas[A_arena].foffset = -1;
  491.  
  492.   if(!use_DPMI)
  493.   {
  494.     areas[A_stack].first_addr = 0x50000000L;
  495.     areas[A_stack].last_addr = 0x8fffffffL;
  496.     areas[A_stack].foffset = -1;
  497.   
  498.     areas[A_vga].first_addr = 0xe0000000L;
  499.     areas[A_vga].last_addr = 0xe03fffffL;
  500.     areas[A_vga].foffset = -1;
  501.   
  502.     areas[A_syms].first_addr = 0xa0000000L;
  503.     areas[A_syms].last_addr = 0xafffffffL;
  504.     areas[A_syms].foffset = -1;
  505.   
  506.     pd = (word32 far *)((long)valloc(VA_640) << 24);
  507.     vcpi_pt = pt = (word32 far *)((long)valloc(VA_640) << 24);
  508.     for (i=0; i<1024; i++)
  509.     {
  510.       pd[i] = 0;
  511.       pd_seg[i] = 0;
  512.     }
  513.   
  514.     if (vcpi_installed)
  515.     {
  516.       link_vcpi(pd,pt);           /*  Get VCPI Page Table  */
  517.       for ( i=0; i<1024; i++)
  518.         if (pt[i] & PT_P)
  519.           pt[i] |= PT_I;
  520.     }
  521.     else
  522.     {
  523.       for (i=0; i < DOS_PAGE; i++)
  524.         pt[i] = ((unsigned long)i<<12) | PT_P | PT_W | PT_I;
  525.       for (; i<1024; i++)
  526.         pt[i] = 0;
  527.     }
  528.  
  529.     pd[0] = 
  530.       pd[0x3c0] = far2pte(pt, PT_P | PT_W | PT_I);  /* map 1:1 1st Mb */
  531.     pd_seg[0] = 
  532.       pd_seg[0x3c0] = (word32)pt >> 24;
  533.   
  534.     gdt_phys.limit = gdt[g_gdt].lim0;
  535.     gdt_phys.base = ptr2linear(&gdt);
  536.     idt_phys.limit = gdt[g_idt].lim0;
  537.     idt_phys.base = ptr2linear(&idt);
  538.   
  539.     handle_screen_swap(pt);
  540.     a_tss.tss_ebx = screen_primary;
  541.     a_tss.tss_ebp = screen_secondary;
  542.     prog_info.linear_address_of_primary_screen = screen_primary;
  543.     prog_info.linear_address_of_secondary_screen = screen_secondary;
  544.   
  545. /* CB changes: two page tables + stuff for graphics page fault handler */
  546. /* to move around page tables in the page directory */
  547. /* OLD:
  548.  * graphics_pt = (word32 far *)((long)valloc(VA_640) << 24);
  549.  * graphics_pt_lin = ptr2linear(graphics_pt);
  550.  * for (i=0; i<1024; i++)
  551.  *   graphics_pt[i] = 0x000a0000L | ((i * 4096L) & 0xffffL) | PT_W | PT_U;
  552.  * pd[0x380] = far2pte(graphics_pt, PT_P | PT_W | PT_U);
  553.  * pd_seg[0x380] = (word32)graphics_pt >> 24;
  554.  */
  555.   graphics_pd       = &pd[0x380];
  556.   graphics_pd_seg     = &pd_seg[0x380];
  557.   graphics_pd_lin     = ptr2linear(graphics_pd);
  558.   graphics_pd_seg_lin = ptr2linear(graphics_pd_seg);
  559.   graphics_pt1              = (word32 far *)((long)valloc(VA_640) << 24);
  560.   graphics_pt2              = (word32 far *)((long)valloc(VA_640) << 24);
  561.   graphics_pt1_lin    = ptr2linear(graphics_pt1);
  562.   graphics_pt2_lin    = ptr2linear(graphics_pt2);
  563.   graphics_pt1_loc    = 0;                            /* first RW page */
  564.   graphics_pt2_loc    = (0x03000000L / 4096L / 1024L);  /* first page of the 16 MB write only area */
  565.   graphics_pd[(word16)graphics_pt1_loc] = far2pte(graphics_pt1,(PT_P | PT_W | PT_U));
  566.   graphics_pd[(word16)graphics_pt2_loc] = far2pte(graphics_pt2,(PT_P | PT_W | PT_U));
  567.   graphics_pd_seg[(word16)graphics_pt1_loc] = (word32)graphics_pt1 >> 24;
  568.   graphics_pd_seg[(word16)graphics_pt2_loc] = (word32)graphics_pt2 >> 24;
  569.   for(i = 0; i < 1024; i++) {
  570.     graphics_pt1[i] = 0L;
  571.     graphics_pt2[i] = 0L;
  572.   }
  573. /* end CB changes */
  574.   
  575.     c_tss.tss_cr3 = 
  576.     a_tss.tss_cr3 = 
  577.     o_tss.tss_cr3 = 
  578.     i_tss.tss_cr3 = 
  579.     p_tss.tss_cr3 = 
  580.     f_tss.tss_cr3 = 
  581.     r_tss.tss_cr3 = 
  582.     v74_tss.tss_cr3 = 
  583.     v78_tss.tss_cr3 = 
  584.     v79_tss.tss_cr3 = far2pte(pd, 0);
  585.   
  586.     a_tss.tss_esi = far2pte(pd,0) >> 12; /* PID */
  587.     prog_info.pid = far2pte(pd,0) >> 12;
  588.   
  589.   }
  590.   else   /* use_DPMI */
  591.   {
  592.   
  593.     if (areas[A_bss].last_addr < 0x11000L)
  594.      areas[A_bss].last_addr = 0x11000L;
  595.     handle_screen_swap(NULL);
  596.     a_tss.tss_ebx = screen_primary;
  597.     a_tss.tss_ebp = screen_secondary;
  598.     prog_info.linear_address_of_primary_screen = screen_primary;
  599.     prog_info.linear_address_of_secondary_screen = screen_secondary;
  600.     a_tss.tss_esi = FP_SEG(paging_buffer);
  601.     prog_info.pid = FP_SEG(paging_buffer);
  602. #if VERBOSE
  603.     fprintf(stderr,"%ld+%ld+%ld = %ld\n", aouthdr.tsize, aouthdr.dsize, aouthdr.bsize,
  604.       aouthdr.tsize+aouthdr.dsize+aouthdr.bsize);
  605. #endif
  606.   
  607.     /* In certain instances, there is a large gap between text and data.  If it
  608.        is larger than the stack size, lets take advantage of it. */
  609.   
  610.     if (areas[A_data].first_addr - areas[A_text].last_addr <= DPMI_STACK)
  611.     {  /* No room, put stack between bss and arena */
  612.       areas[A_stack].first_addr = (areas[A_bss].last_addr + 1 + 0xfff) & ~0xfff;
  613.       if (areas[A_stack].first_addr < 0x11000L) 
  614.         areas[A_stack].first_addr = 0x11000L; /* Some bizzare windows bug */
  615.       areas[A_stack].last_addr = areas[A_stack].first_addr + DPMI_STACK - 1;
  616.       areas[A_arena].first_addr = areas[A_stack].last_addr + 1;
  617.       areas[A_arena].last_addr = areas[A_stack].last_addr;
  618.   } else {  /* Put stack in gap */
  619.       areas[A_stack].last_addr = areas[A_data].first_addr - 1;
  620. /*    areas[A_stack].first_addr = areas[A_stack].last_addr - DPMI_STACK + 1; */
  621.       areas[A_stack].first_addr = (areas[A_text].last_addr + 1 + 0xfff) & ~0xfff;
  622.       if (areas[A_stack].first_addr < 0x11000L) 
  623.         areas[A_stack].first_addr = 0x11000L; /* Some bizzare windows bug */
  624.     }
  625.     areas[A_vga].first_addr =
  626.      areas[A_syms].first_addr =
  627.      areas[A_syms2].first_addr = 1; /* Not used */
  628.     areas[A_vga].last_addr =
  629.      areas[A_syms].last_addr =
  630.      areas[A_syms2].last_addr = 0;   /* len zero */
  631.   
  632.     /* Here and in changeBreak we use 64K breaks to minimize calls to DPMI */
  633.     newbytes = (areas[A_arena].last_addr + 1 + DPMIgetpage) & ~DPMIgetpage;
  634.     DPMIprotectedMode();
  635.     if (! DPMIalloc(&DPMImem, newbytes))
  636.     {
  637.       DPMIrealMode();
  638.       fprintf(stderr,"DPMI: Not enough memory (0x%08lx bytes).\n", newbytes);
  639.       exit(1);
  640.     }
  641.     DPMIselect = DPMIselector(4);
  642.     if (DPMIselect == 0)
  643.     {
  644.       DPMIrealMode();
  645.       fprintf(stderr,"DPMI: Not enough selectors.\n");
  646.       exit(1);
  647.     }
  648.     setDPMISelectors(1);
  649.     DPMIassignSelector(DPMIselect+24, 0xc0b3, 0L, 0xfffffL);
  650.     DPMIrealMode();
  651.  
  652.     core_selector =  
  653.     a_tss.tss_gs =
  654.     prog_info.selector_for_linear_memory = (word16)(DPMIselect+24);
  655.   
  656.     a_tss.tss_eax = (word32)(DPMIselect + 24) << 16;  /* Hi word for "core" selector */
  657.     arena_ds = a_tss.tss_ds = a_tss.tss_es = a_tss.tss_fs = DPMIselect;
  658.     arena_cs = a_tss.tss_cs = DPMIselect + 8;
  659.     a_tss.tss_ss = DPMIselect + 16;
  660.     a_tss.tss_esp = areas[A_stack].last_addr + 1;
  661.     a_tss.tss_eflags = 0x0202;
  662.  
  663.     r_tss.tss_es = r_tss.tss_fs = DPMIselect;
  664.     r_tss.tss_cs = DPMIselect + 8;
  665.   
  666.     loadAout(&areas[A_text]);
  667.     loadAout(&areas[A_data]);
  668.     Pmemset(DPMIselect, areas[A_bss].first_addr, 0, areas[A_bss].last_addr + 1 - areas[A_bss].first_addr);
  669.     Pmemset(DPMIselect, areas[A_arena].first_addr, 0, newbytes - areas[A_arena].first_addr);
  670.   
  671.     close(aout_f);
  672.   } /* end else use_DPMI */
  673.  
  674. #if VERBOSE
  675.     for (i=0; i<5; i++)
  676.       fprintf(stderr,"%d %-10s %08lx-%08lx (offset 0x%08lx)\n", i, aname[i], areas[i].first_addr, areas[i].last_addr, areas[i].foffset);
  677. #endif
  678. }
  679.  
  680. static update_status(int c, int col)
  681. {
  682.   int r;
  683.   r = peek(screen_seg, 2*79);
  684.   poke(screen_seg, 2*col, c);
  685.   return r;
  686. }
  687.  
  688. static int cant_ask_for(int32 amount)
  689. {
  690.   static word32 reserved = 0;
  691.   static word32 used_at_first = 0;
  692.   word32 max;
  693.   
  694.   if (use_DPMI)
  695.     return 0;
  696.   if (used_at_first == 0)
  697.     used_at_first = (valloc_used() - dalloc_used()) * 4096L + 8192L /* stack */;
  698.   max = valloc_max_size()*4092L - used_at_first;    /* 4096 - PTE */
  699.  
  700.   if (reserved + amount >= max)
  701.     max += dalloc_max_size() * 4092L;
  702.  
  703.   if (reserved + amount < max)
  704.   {
  705.     reserved += amount;
  706.     return 0;
  707.   }
  708.   return 1;
  709. }
  710.  
  711. word32 paging_brk(word32 b)
  712. {
  713.   word32 r;
  714.  
  715.   r = (areas[A_arena].last_addr - ARENA + 1 + 7) & ~7;  /* Even value */
  716.   if (use_DPMI)
  717.     if (! changeBreak(b)) return -1L;
  718.   if (cant_ask_for(b-r))
  719.     return -1L;
  720.   areas[A_arena].last_addr = b + ARENA - 1;
  721.   return r;
  722. }
  723.  
  724. word32 paging_sbrk(int32 b)
  725. {
  726.   word32 r;
  727.  
  728.   r = (areas[A_arena].last_addr - ARENA + 1 + 7) & ~7;  /* Even value */
  729.   if (use_DPMI)
  730.     if (! changeBreak(r + b)) return -1L;
  731.   if (cant_ask_for(b))
  732.     return -1L;
  733.   areas[A_arena].last_addr = r + b + ARENA - 1;
  734.   return r;
  735. }
  736.  
  737. int page_is_valid(word32 vaddr)
  738. {
  739.   int a;
  740.   for (a=0; a<MAX_AREA; a++)
  741.     if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  742.       return 1;
  743.   if ( use_DPMI )
  744.     return 0;
  745.   if (vaddr >= 0xf0000000L)
  746.     return 1;
  747.   return 0;
  748. }
  749.  
  750. int page_in(void)
  751. {
  752.   int old_status;
  753.   TSS *old_util_tss;
  754.   word32 far *pt;
  755.   word32 vaddr, cnt32;
  756.   word32 eaddr, vtran, vcnt, zaddr;
  757.   int pdi, pti, pn, a, count;
  758.   unsigned dblock;
  759.  
  760.   if (use_DPMI)
  761.     return 1;
  762.  
  763. #if 0
  764.   unsigned char buf[100];
  765.   sprintf(buf, "0x%08lx", a_tss.tss_cr2 - ARENA);
  766.   for (a=0; buf[a]; a++)
  767.     poke(screen_seg, 80+a*2, 0x0600 | buf[a]);
  768. #endif
  769.  
  770.   old_util_tss = utils_tss;
  771.   utils_tss = &f_tss;
  772.   vaddr = tss_ptr->tss_cr2;
  773.  
  774.   for (a=0; a<MAX_AREA; a++)
  775.     if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  776.       goto got_area;
  777.  
  778.   if (vaddr >= 0xf0000000L)
  779.   {
  780.     pdi = (word16)(vaddr >> 22) & 0x3ff;
  781.     if (!(pd[pdi] & PT_P))      /* put in a mapped page table */
  782.     {
  783.       pn = valloc(VA_640);
  784.       pt = (word32 far *)((word32)pn << 24);
  785.       if (pd[pdi] & PT_S)
  786.       {
  787.         dread(paging_buffer, (word16)(pd[pdi]>>12));
  788.         movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
  789.         dfree((word16)(pd[pdi]>>12));
  790.         pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  791.         pd_seg[pdi] = pn;
  792.       }
  793.       else
  794.       {
  795.         pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  796.         pd_seg[pdi] = pn;
  797.         vaddr &= 0x0fc00000L;
  798.         for (pti = 0; pti < 1024; pti++)
  799.           pt[pti] = PT_P | PT_W | PT_I | vaddr | (((word32)pti)<<12);
  800.       }
  801.       return 0;
  802.     }
  803.     pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  804.     vaddr &= 0x0ffff000L;
  805.     pti = (word16)(vaddr>>12) & 0x3ff;
  806.     pt[pti] = vaddr | PT_P | PT_W | PT_I;
  807.     return 0;
  808.   }
  809.  
  810.   segfault(tss_ptr->tss_cr2);
  811.   return 1;
  812.  
  813. got_area:
  814.   vaddr &= 0xFFFFF000L;  /* points to beginning of page */
  815. #if 0 /* handled in protected mode for speed */
  816.   if (a == A_vga)
  817.     return graphics_fault(vaddr, graphics_pt);
  818. #endif
  819.  
  820. #if VERBOSE
  821.     printf("area(%d) - ", a);
  822. #endif
  823.  
  824.   if ((a == A_bss) & (vaddr < areas[a].first_addr)) /* bss, but data too */
  825.   {
  826. #if VERBOSE
  827.       printf("split page (data/bss) detected - ");
  828. #endif
  829.     a = A_data; /* set to page in data */
  830.   }
  831.  
  832.   if (topline_info)
  833.     old_status = update_status(achar[a] | 0x0a00, 78);
  834. #if VERBOSE
  835.   printf("Paging in %s block for vaddr %#010lx -", aname[a], tss_ptr->tss_cr2-ARENA);
  836. #endif
  837.   pdi = (word16)(vaddr >> 22) & 0x3ff;
  838.   if (!(pd[pdi] & PT_P))        /* put in an empty page table if required */
  839.   {
  840.     pn = valloc(VA_640);
  841.     pt = (word32 far *)((word32)pn << 24);
  842.     if (pd[pdi] & PT_I)
  843.     {
  844.       dread(paging_buffer, (word16)(pd[pdi]>>12));
  845.       movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
  846.       dfree((word16)(pd[pdi] >> 12));
  847.       pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  848.       pd_seg[pdi] = pn;
  849.     }
  850.     else
  851.     {
  852.       pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  853.       pd_seg[pdi] = pn;
  854.       for (pti=0; pti<1024; pti++)
  855.         pt[pti] = PT_W | PT_S;
  856.     }
  857.   }
  858.   else
  859.     pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  860.   pti = (word16)(vaddr >> 12) & 0x3ff;
  861.   if (pt[pti] & PT_P)
  862.   {
  863.     utils_tss = old_util_tss;
  864.     if (topline_info)
  865.       update_status(old_status, 78);
  866.     return 0;
  867.   }
  868.   count = MAX_PAGING_NUM;
  869.   if (count > mem_avail/4)
  870.     count = 1;
  871.   if (pti + count > 1024)
  872.     count = 1024 - pti;
  873.   if (vaddr + count*4096L > areas[a].last_addr+4096L)
  874.     count = (word16)((areas[a].last_addr - vaddr + 4095) / 4096);
  875.   if (count < 1)
  876.     count = 1;
  877.   zaddr = eaddr = -1;
  878.   vtran = vaddr;
  879.   vcnt = 0;
  880.   for (; count; count--, pti++, vaddr+=4096)
  881.   {
  882.     if (pt[pti] & PT_P)
  883.       break;
  884.     if (eaddr != -1 && (pt[pti] & PT_I) != 0) 
  885.       break;  /* EastWind 1993 */
  886.     dblock = (word16)(pt[pti] >> 12);
  887.     pn = valloc(VA_1M);
  888.     pt[pti] &= 0xfffL & ~(word32)(PT_A | PT_D);
  889.     pt[pti] |= ((word32)pn << 12) | PT_P;
  890.  
  891.     if (pt[pti] & PT_I)
  892.     {
  893. #if VERBOSE
  894.       printf(" swap");
  895. #endif
  896.       dread(paging_buffer, dblock);
  897.       dfree(dblock);
  898.       memput(vaddr, paging_buffer, 4096);
  899.       pt[pti] &= ~(word32)(PT_A | PT_D);  /* clean dirty an accessed bits (set by memput) */
  900.     }
  901.     else
  902.     {
  903.       pt[pti] &= ~(word32)(PT_C);
  904.       if (areas[a].foffset != -1)
  905.       {
  906. #if VERBOSE
  907.         if (a == A_emu)
  908.           printf(" emu");
  909.         else
  910.           printf(" exec");
  911. #endif
  912.         if (eaddr == -1)
  913.         {
  914.           eaddr = areas[a].foffset + (vaddr - areas[a].first_addr);
  915.           vtran = vaddr;
  916.         }
  917.         cnt32 = areas[a].last_addr - vaddr + 1;
  918.         if (cnt32 > 4096)
  919.           cnt32 = 4096;
  920.         else
  921.           zaddr = vaddr;
  922.         vcnt += cnt32;
  923.       }
  924.       else
  925.       {
  926.         zero32(vaddr);
  927. #if VERBOSE
  928.         printf(" zero");
  929. #endif
  930.       }
  931.       pt[pti] |= PT_I;
  932.     }
  933. /*  if (paged_out_something) */
  934.       break;
  935.   }
  936.   if (eaddr != -1)
  937.   {
  938.     int cur_f, rsize, vc;
  939.     cur_f = areas[a].fileno;
  940.     lseek(cur_f, eaddr, 0);
  941.     rsize = read(cur_f, paging_buffer, (word16)vcnt);
  942.     if (rsize < vcnt)
  943.       memset(paging_buffer+rsize, 0, (word16)(vcnt-rsize));
  944.     if (zaddr != -1)
  945.       zero32(zaddr);
  946.     memput(vtran, paging_buffer, vcnt);
  947.     vc = (word16)(vcnt / 4096); /* don't reset BSS parts */
  948.     while (vc)
  949.     {
  950.       pdi = (word16)(vtran >> 22);
  951.       pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  952.       pti = (word16)(vtran >> 12) & 0x3ff;
  953.       pt[pti] &= ~(word32)(PT_A | PT_D);  /* clean dirty an accessed bits (set by memput) */
  954.       vc--;
  955.       vtran += 4096;
  956.     }
  957.   }
  958. #if VERBOSE
  959.   printf("\n");
  960. #endif
  961.   utils_tss = old_util_tss;
  962.   if (topline_info)
  963.     update_status(old_status, 78);
  964.   return 0;
  965. }
  966.  
  967. static fInPageOutEverything = 0;
  968. static last_po_pdi = 0;
  969. static last_po_pti = 0;
  970. static last_pti = 0;
  971.  
  972. unsigned page_out(int where) /* return >= 0 page which is paged out, 0xffff if not */
  973. {
  974.   int start_pdi, start_pti, pti;
  975.   word32 far *pt, v, rv;
  976.   unsigned dblock;
  977.   int old_status;
  978.   if (topline_info)
  979.   {
  980.     old_status = update_status('>' | 0x0a00, 79);
  981.   }
  982.   start_pdi = last_po_pdi;
  983.   start_pti = last_po_pti;
  984.   if (where == VA_640)
  985.   {
  986.     for (pti = last_pti+1; pti != last_pti; pti = (pti+1)%1024)
  987.       if ((pd[pti] & (PT_P | PT_S)) == (PT_P | PT_S))
  988.       {
  989.         dblock = dalloc();
  990.         movedata(pd_seg[pti]<<8, 0, _DS, FP_OFF(paging_buffer), 4096);
  991.         dwrite(paging_buffer, dblock);
  992. #if VERBOSE
  993.         printf ("out_640 %d\n", pti);
  994. #endif
  995.         pd[pti] &= 0xfff & ~(word32)(PT_P); /* no longer present */
  996.         pd[pti] |= (long)dblock << 12;
  997.         if (topline_info)
  998.           update_status(old_status, 79);
  999.         last_pti = pti;
  1000.         return pd_seg[pti];
  1001.       }
  1002.     return -1;
  1003.   }
  1004.   pt = (word32 far *)((word32)(pd_seg[last_po_pdi]) << 24);
  1005.   do {
  1006.     if ((pd[last_po_pdi] & (PT_P | PT_S)) == (PT_P | PT_S))
  1007.     {
  1008.       if ((pt[last_po_pti] & (PT_P | PT_S)) == (PT_P | PT_S))
  1009.       {
  1010.         rv = pt[last_po_pti] >> 12;
  1011.         v = ((word32)last_po_pdi << 22) | ((word32)last_po_pti << 12);
  1012.         if (!fInPageOutEverything)
  1013.           if ((v & 0xfffff000L) == ((tss_ptr->tss_eip + ARENA) & 0xfffff000L) ||
  1014.               (v & 0xfffff000L) == ((tss_ptr->tss_esp + ARENA) & 0xfffff000L))
  1015.           {
  1016. #if VERBOSE
  1017.             printf("\nskip: v=%08lx - ", v);
  1018. #endif
  1019.             goto bad_choice;
  1020.           }
  1021.         if (pt[last_po_pti] & (PT_C | PT_D))
  1022.         {
  1023.           pt[last_po_pti] |= PT_C;
  1024.           dblock = dalloc();
  1025.           memget(v, paging_buffer, 4096);
  1026. #if VERBOSE
  1027.           printf ("dout %08lx", ((word32)last_po_pdi<<22) | ((word32)last_po_pti<<12));
  1028. #endif
  1029.           dwrite(paging_buffer, dblock);
  1030.           pt[last_po_pti] &= 0xfff & ~PT_P; /* no longer present */
  1031.           pt[last_po_pti] |= (long)dblock << 12;
  1032.         }
  1033.         else
  1034.         {
  1035.           pt[last_po_pti] = PT_W | PT_S;
  1036. #if VERBOSE
  1037.           printf ("dflush %08lx", ((word32)last_po_pdi<<22) | ((word32)last_po_pti<<12));
  1038. #endif
  1039.         }
  1040.         if (topline_info)
  1041.           update_status(old_status, 79);
  1042.         return (word16)rv;
  1043.       }
  1044.     }
  1045.     else /* imagine we just checked the last entry */
  1046.       last_po_pti = 1023;
  1047.  
  1048. bad_choice:
  1049.     if (++last_po_pti == 1024)
  1050.     {
  1051.       last_po_pti = 0;
  1052.       if (++last_po_pdi == 1024)
  1053.         last_po_pdi = 0;
  1054.       pt = (word32 far *)((word32)(pd_seg[last_po_pdi]) << 24);
  1055.     }
  1056.   } while ((start_pdi != last_po_pdi) || (start_pti != last_po_pti));
  1057.   if (topline_info)
  1058.     update_status(old_status, 79);
  1059.   return 0xffff;
  1060. }
  1061.  
  1062. unsigned pd_dblock;
  1063.  
  1064. extern int valloc_initted;
  1065. extern void vfree_640(void);
  1066. extern void vrecover_640(void);
  1067.  
  1068. void page_out_everything(void)
  1069. {
  1070.   int pdi, i;
  1071.   word32 opde;
  1072.   unsigned ptb;
  1073.   void far *fp;
  1074.  
  1075.   if(use_DPMI)
  1076.   {
  1077.     saveDPMIstate();
  1078.     return;
  1079.   }
  1080.  
  1081.   fInPageOutEverything = 1;
  1082.  
  1083. #ifndef KEEP_ON_EXEC
  1084.   while (page_out(-1) != 0xffff)
  1085.   {
  1086.     vfree();
  1087.   }
  1088. #endif
  1089.   for (pdi=0; pdi<1024; pdi++)
  1090.     if (pd[pdi] & PT_P)
  1091.     {
  1092.       ptb = dalloc();
  1093.       opde = pd[pdi] & 0xfffff001L;
  1094.       fp = (word32 far *)((word32)pd_seg[pdi] << 24);
  1095.       movedata(FP_SEG(fp), FP_OFF(fp), _DS, FP_OFF(paging_buffer), 4096);
  1096.       dwrite(paging_buffer, ptb);
  1097.       vfree();
  1098.       pd[pdi] = (pd[pdi] & (0xFFF&~PT_P)) | ((word32)ptb<<12);
  1099.       for (i=pdi+1; i<1024; i++)
  1100.         if ((pd[i] & 0xfffff001L) == opde)
  1101.           pd[i] = pd[pdi];
  1102.     }
  1103.   movedata(FP_SEG(pd), FP_OFF(pd), _DS, FP_OFF(paging_buffer), 4096);
  1104.   pd_dblock = dalloc();
  1105.   dwrite(paging_buffer, pd_dblock);
  1106.   vfree();
  1107. #ifndef KEEP_ON_EXEC
  1108.   vcpi_flush();
  1109.   valloc_uninit();
  1110. #else
  1111.   vfree_640();
  1112. #endif
  1113. }
  1114.  
  1115. void page_in_everything(void)
  1116. {
  1117.   int pdi, i;
  1118.   word32 opde;
  1119.   unsigned ptb;
  1120.   word32 far *pt;
  1121.   unsigned pta;
  1122.  
  1123.   if(use_DPMI)
  1124.   {
  1125.     restoreDPMIstate();
  1126.     return;
  1127.   }
  1128.  
  1129.   fInPageOutEverything = 0;
  1130.  
  1131. #ifndef KEEP_ON_EXEC
  1132.   valloc_initted = 0;
  1133. #else
  1134.   vrecover_640();
  1135. #endif
  1136.   pta = valloc(VA_640);
  1137.   pd = (word32 far *)((word32)pta << 24);
  1138.   dread(paging_buffer, pd_dblock);
  1139.   dfree(pd_dblock);
  1140.   movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pd), FP_OFF(pd), 4096);
  1141.   for (pdi=0; pdi<1024; pdi++)
  1142.     if (pd[pdi] && !(pd[pdi] & PT_P))
  1143.     {
  1144.       pta = valloc(VA_640);
  1145.       opde = pd[pdi] & 0xfffff001L;
  1146.       pt = (word32 far *)((word32)pta << 24);
  1147.       ptb = (word16)(opde >> 12);
  1148.       dread(paging_buffer, ptb);
  1149.       dfree(ptb);
  1150.       movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
  1151.       if (pdi == 0)
  1152.         vcpi_pt = (word32 far *)((word32)pta << 24);
  1153.       pd[pdi] = pn2pte(pta, (pd[pdi] & 0xFFF) | PT_P);
  1154.       pd_seg[pdi] = pta;
  1155.       for (i=pdi+1; i<1024; i++)
  1156.         if ((pd[i] & 0xfffff001L) == opde)
  1157.         {
  1158.           pd[i] = pd[pdi];
  1159.           pd_seg[i] = pd_seg[pdi];
  1160.         }
  1161.     }
  1162. /* CB changes: two tables + page directory stuff */
  1163. /* OLD:
  1164.  * graphics_pt = (word32 far *)((long)pd_seg[0x380] << 24);
  1165.  * graphics_pt_lin = ptr2linear(graphics_pt);
  1166.  */
  1167.   graphics_pd    = &pd[0x380];
  1168.   graphics_pd_lin  = ptr2linear(graphics_pd);
  1169.   graphics_pt1           = (word32 far *)((word32)graphics_pd_seg[(word16)graphics_pt1_loc] << 24);
  1170.   graphics_pt2           = (word32 far *)((word32)graphics_pd_seg[(word16)graphics_pt2_loc] << 24);
  1171.   graphics_pt1_lin = ptr2linear(graphics_pt1);
  1172.   graphics_pt2_lin = ptr2linear(graphics_pt2);
  1173.   for(i = 0; i < 1024; i++) {
  1174.     graphics_pt1[i] = 0L;
  1175.     graphics_pt2[i] = 0L;
  1176.   }
  1177. /* end CB changes */
  1178. }
  1179.  
  1180.  
  1181. static word32 emu_start_ip_val = 0;
  1182.  
  1183. word32 emu_start_ip()
  1184. {
  1185.   return emu_start_ip_val;
  1186. }
  1187.  
  1188. int emu_install(char *filename)
  1189. {
  1190.   FILEHDR filehdr;
  1191.   AOUTHDR aouthdr;
  1192.   GNU_AOUT gnu_aout;
  1193.   int emu_f;
  1194.  
  1195.   areas[A_emu].first_addr = EMU_TEXT+ARENA;
  1196.   areas[A_emu].last_addr = EMU_TEXT-1+ARENA;
  1197.   areas[A_emu].foffset = 0;
  1198.  
  1199.   if (use_DPMI)
  1200.     return 0;
  1201.   if (filename == 0)
  1202.     return 0;
  1203.   emu_f = open(filename, O_RDONLY|O_BINARY);
  1204.   if (emu_f < 0)
  1205.   {
  1206.     fprintf(stderr, "Can't open 80387 emulator file <%s>\n", filename);
  1207.     return 0;
  1208.   }
  1209.   areas[A_emu].fileno = emu_f;
  1210.   
  1211.   read(emu_f, &filehdr, sizeof(filehdr));
  1212.   if (filehdr.f_magic != 0x14c)
  1213.   {
  1214.     lseek(emu_f, 0L, 0);
  1215.     read(emu_f, &gnu_aout, sizeof(gnu_aout));
  1216.     emu_start_ip_val = gnu_aout.entry;
  1217.     aouthdr.tsize = gnu_aout.tsize;
  1218.     aouthdr.dsize = gnu_aout.dsize;
  1219.     aouthdr.bsize = gnu_aout.bsize;
  1220.   }
  1221.   else
  1222.   {
  1223.     read(emu_f, &aouthdr, sizeof(aouthdr));
  1224.     emu_start_ip_val = aouthdr.entry;
  1225.   }
  1226.  
  1227.   areas[A_emu].last_addr += aouthdr.tsize + aouthdr.dsize + aouthdr.bsize + (emu_start_ip_val & 0xff);
  1228.   return 1;
  1229. }
  1230.  
  1231. word32 stack_used(void)
  1232. {
  1233.   int pdi,pti;
  1234.   word32 far *pt;
  1235.  
  1236.   for(pdi=0x140;pdi<0x240;pdi++)
  1237.     if( pd[pdi] & PT_I ) {  /* really should check for PT_P here, but */
  1238.       pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  1239.       for(pti=0;pti<1024;pti++)
  1240.         if( pt[pti] & PT_I )
  1241.           return ((word32)(0x23f-pdi) << 22) | ((word32)(1024-pti) << 12);
  1242.     }
  1243.   return 0L;  /* No stack pd entries found! */
  1244. }
  1245.